import Dep from './observe/dep';
import { observe } from './observe/index';
import Watcher from './observe/watcher';
export function initState(vm) {
    // 存放计算属性的watcher
    vm._computedWatcher = {};
    const options = vm.$options || {};
    if (options.props) {
        initProps(options.props);
    }
    if (options.method) {
        initMethod(options.method, vm);
    }
    if (options.data) {
        initData(options.data, vm);
    }
    if (options.computed) {
        initComputed(options.computed, vm);
    }
    if (options.watch) {
        initWatcher(options.watch, vm);
    }

    function initProps() {

    }

    function initMethod(methods, vm) {
        for (let method in methods) {
            vm[method] = methods[method].bind(vm);
        }
    }

    function initData(data = {}, vm) {
        data = vm._data = typeof data === 'function' ? data.call(vm) : data;
        observe(data);

        // 访问vm.xxx 代理到vm._data.xxx
        for (let key in data) {
            proxy(vm, "_data", key);
        }
    }

    function initComputed(computed, vm) {
        vm._computed = computed;
        for (let prop in computed) {
            let getter = typeof computed[prop] === 'function' ? computed[prop] : computed[prop].get;
            // 与watcher关联 通过watcher去调用getter
            vm._computedWatcher[prop] = new Watcher(vm, getter, () => { }, { lazy: true });
            console.log()
            defineComputed(vm, computed, prop);

            // 代理到vm上
            proxy(vm, '_computed', prop);
        }
    }
    // 定义计算属性响应式
    function defineComputed(vm, computed, key) {
        let shareOptions = {};
        shareOptions.get = createComputed(vm, key);

        Object.defineProperty(computed, key, shareOptions);
    }

    // 当get计算属性的值的时候，会走到这
    function createComputed(vm, key) {
        return function () {
            const watcher = vm._computedWatcher[key];
            if (watcher) {
                // 第一次默认dirty肯定为脏值，取值 如果不是脏值，就不用管
                if (watcher.dirty) {
                    watcher.evaluate();
                }
                if (Dep.target) {
                    // 此时还有渲染watcher，让属性也要去记住渲染watcher
                    watcher.depend();// 让计算属性watcher中存有的dep去记住渲染watcher
                }
            }
            return watcher.value;
        }
    }

    function initWatcher(handlers, vm) {
        for (let handler in handlers) {
            let target = handlers[handler]
            if (Array.isArray(target)) { // 数组
                for (let i = 0; i < target.length; i++) {
                    createWatcher(target[i], handler, vm);
                }
            } else { // 函数 字符串 对象
                createWatcher(target, handler, vm);
            }
        }

    }
    function createWatcher(handler, key, vm) {
        let options = {};
        if (typeof handler === 'object') {
            // 是对象
            options = handler
            handler = options.handler;
        } else if (typeof handler === 'string') {
            handler = vm[handler];
        }
        if (options.immediate) {
            handler.call(vm, vm[key]);
        }
        options.user = true;
        new Watcher(vm, key, handler, options);
    }


    // 将computed data watcher的属性代理到vm上
    function proxy(vm, target, key) {
        Object.defineProperty(vm, key, {
            get() {
                return vm[target][key];
            },
            set(newValue) {
                vm[target][key] = newValue;
            }
        })
    }
}